package com.bieber.server;

import com.bieber.common.Constants;
import com.bieber.server.config.ServerConfig;
import com.bieber.server.exception.ErrorStatus;
import com.bieber.server.exception.FileTransportException;
import io.netty.channel.Channel;

import java.io.*;

/**
 * Created by bieber on 2015/8/19.
 * 相对于本节点来说是写的操作
 */
public class Acceptor {
    

    private Channel remoteChannel;
    

    private RandomAccessFile accessFile;
    
    private File root;

    private volatile boolean isWorking=false;

    private String currentFileName;

    private long currentFileSize;

    private long acceptedSize;

    public Acceptor(ServerConfig config, Channel remoteChannel, String nodeNode) {
        this.remoteChannel = remoteChannel;
        root  = new File(config.getAcceptFileDir()+File.separator+nodeNode);
        if(!root.exists()){
            boolean ret = root.mkdirs();
            if(!ret){
                throw  new RuntimeException("failed to mkdirs "+root.getPath());
            }
        }
    }


    public Channel getRemoteChannel() {
        return remoteChannel;
    }

    public void startAcceptFile(String fileName, long fileSize) throws FileTransportException{
        //如果当前节点挂了，那么不在允许开始处理写入请求
        if(!Transporter.isRunning()){
            throw new FileTransportException(ErrorStatus.CURRENT_NODE_IS_SHUTDOWN);
        }
        if(accessFile!=null){
            throw new FileTransportException(ErrorStatus.ACCEPT_FILE_NOT_FINISHED);
        }
        try {
            //开始写文件说明当前这个Writer处于工作状态，不能立即断开
            isWorking=true;
            File target= new File(root,fileName);
            Constants.COMMON_LOGGER.info("starting accept file [{}]",fileName);
            if(target.exists()){
                boolean ret = target.delete();
                if(!ret){
                    Constants.COMMON_LOGGER.warn("failed to delete file "+target.getPath());
                }
            }
            accessFile = new RandomAccessFile(target,"rw");
            accessFile.setLength(fileSize);
            currentFileName=fileName;
            currentFileSize=fileSize;
            acceptedSize = 0;
            Transporter.reportCurrentAcceptStatus(currentFileName, currentFileSize, acceptedSize);
        } catch (FileNotFoundException e) {
            throw new FileTransportException(ErrorStatus.FILE_NOT_FOUND,e);
        } catch (IOException e) {
            throw new FileTransportException(ErrorStatus.ACCEPT_FILE_ERROR,e);
        }
    }
    
    public void acceptFile(long offset, byte[] bytes) throws FileTransportException {
        try {
            accessFile.seek(offset);
            accessFile.write(bytes,0,bytes.length);
            acceptedSize +=bytes.length;
            Transporter.reportCurrentAcceptStatus(currentFileName, currentFileSize, acceptedSize);
        } catch (IOException e) {
            throw new FileTransportException(ErrorStatus.ACCEPT_FILE_ERROR,e);
        }
    }
    
    public void finished() throws FileTransportException {
         try {
             accessFile.close();
             accessFile=null;
             Constants.COMMON_LOGGER.info("finished accept file");
        } catch (Exception e) {
            throw new FileTransportException(ErrorStatus.ACCEPT_FILE_ERROR,e);
        }finally {
             isWorking=false;
         }
    }

    public boolean isWorking() {
        return isWorking&&remoteChannel.isActive();
    }
}
